package com.example.jucsample.threadpool;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhenwei.wu
 * @date 2021/3/17
 */
public class ThreadPoolTest {

    public static void main(String[] args) throws Exception {
        // https://juejin.cn/post/6935355388741025823
        // corePoolSize     核心线程数
        // maximumPoolSize  最大线程数，队列满后启用
        // keepAliveTime    空闲时间，时间到就销毁
        // workQueue        任务队列
        // threadFactory    线程工厂，创建线程（比如：命名）
        // handler          决绝策略

        keepAliveTime();
//        corePoolSize();
//        maxPoolSize();
//        handler();


    }

    private static void handler() {

        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();          //丢弃任务，并抛出异常
//        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();        //丢弃任务，也不抛出异常
//        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();    //丢弃队首任务
//        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();    //同步任务

//        RejectedExecutionHandler handler = (r, executor) -> {
//            System.out.println(String.format("%s 不执行", r));
//        };    //自定义，不执行并打印


        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1), new ThreadFactory() {
            AtomicInteger serialNo = new AtomicInteger();

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "test-pool-" + serialNo.getAndIncrement());
            }
        }, handler);

        for (int i = 0; i < 4; i++) {
            int n = i;
            executor.submit(() -> {
                Thread.sleep(1000L);
                System.out.println(String.format("%s executing task %s", Thread.currentThread().getName(), n));
                return "";
            });
        }


    }

    private static void corePoolSize() throws Exception {
        // 调整maximumPoolSize，验证core线程不会销毁，core和非core线程本质没有区别，线程池只会维持core的数量
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1), new ThreadFactory() {
            AtomicInteger serialNo = new AtomicInteger();

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "test-pool-" + serialNo.getAndIncrement());
            }
        }, new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < 3; i++) {
            int n = i;
            executor.submit(() -> {
                Thread.sleep(1000L);
                System.out.println(String.format("%s executing task %s", Thread.currentThread().getName(), n));
                return "";
            });
        }
        Thread.sleep(2000L);
        executor.submit(() -> {
            Thread.sleep(1000L);
            System.out.println(String.format("%s executing task %s", Thread.currentThread().getName(), "test"));
            return "";
        });


    }

    public static void maxPoolSize() throws Exception {
        // 调整workQueue长度，验证workQueue满后启用非core线程
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 4, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), new ThreadFactory() {
            AtomicInteger serialNo = new AtomicInteger();

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "test-pool-" + serialNo.getAndIncrement());
            }
        }, new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < 5; i++) {
            int n = i;
            executor.submit(() -> {
                Thread.sleep(1000L);
                System.out.println(String.format("%s executing task %s", Thread.currentThread().getName(), n));
                return "";
            });
        }

    }

    public static void keepAliveTime() throws Exception {
        // 调整keepAliveTime，验证core不会销毁，非core会销毁
        ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10), new ThreadFactory() {
            AtomicInteger serialNo = new AtomicInteger();

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "test-pool-" + serialNo.getAndIncrement());
            }
        }, new ThreadPoolExecutor.AbortPolicy());

        executor.submit(() -> {
            Thread.sleep(1000L);
            System.out.println(String.format("%s executing task1", Thread.currentThread().getName()));
            return "";
        });

        Thread.sleep(3000L);

        executor.submit(() -> {
            Thread.sleep(1000L);
            System.out.println(String.format("%s executing task2", Thread.currentThread().getName()));
            return "";
        });
    }

}
